home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / bin / help2man < prev    next >
Text File  |  2005-10-13  |  14KB  |  622 lines

  1. #!/usr/bin/perl -w
  2.  
  3. # Generate a short man page from --help and --version output.
  4. # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software
  5. # Foundation, Inc.
  6.  
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2, or (at your option)
  10. # any later version.
  11.  
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. # GNU General Public License for more details.
  16.  
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software Foundation,
  19. # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20.  
  21. # Written by Brendan O'Dea <bod@debian.org>
  22. # Available from ftp://ftp.gnu.org/gnu/help2man/
  23.  
  24. use 5.005;
  25. use strict;
  26. use Getopt::Long;
  27. use Text::Tabs qw(expand);
  28. use POSIX qw(strftime setlocale LC_ALL);
  29. use locale;
  30.  
  31. my $this_program = 'help2man';
  32. my $this_version = '1.33';
  33.  
  34. my $have_gettext;
  35. BEGIN {
  36.     eval {
  37.     require Locale::gettext;
  38.     Locale::gettext->import;
  39.     $have_gettext = 1;
  40.     };
  41.  
  42.     unless ($have_gettext)
  43.     {
  44.     *gettext = sub { $_[0] };
  45.     *textdomain = sub {};
  46.     }
  47. }
  48.  
  49. sub _ { gettext @_ }
  50. sub N_ { $_[0] }
  51.  
  52. textdomain $this_program;
  53. {
  54.     my ($user_locale) = grep defined && length,
  55.     (map $ENV{$_}, qw(LANGUAGE LC_ALL LC_MESSAGES LANG)), 'C';
  56.  
  57.     sub kark # die with message formatted in the invoking user's locale
  58.     {
  59.     setlocale LC_ALL, $user_locale;
  60.     my $fmt = gettext shift;
  61.     die +(sprintf $fmt, @_), "\n";
  62.     }
  63. }
  64.  
  65. my $version_info = sprintf _(<<'EOT'), $this_program, $this_version;
  66. GNU %s %s
  67.  
  68. Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software
  69. Foundation, Inc.
  70. This is free software; see the source for copying conditions.  There is NO
  71. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  72.  
  73. Written by Brendan O'Dea <bod@debian.org>
  74. EOT
  75.  
  76. my $help_info = sprintf _(<<'EOT'), $this_program, $this_program;
  77. `%s' generates a man page out of `--help' and `--version' output.
  78.  
  79. Usage: %s [OPTION]... EXECUTABLE
  80.  
  81.  -n, --name=STRING       description for the NAME paragraph
  82.  -s, --section=SECTION   section number for manual page (1, 6, 8)
  83.  -m, --manual=TEXT       name of manual (User Commands, ...)
  84.  -S, --source=TEXT       source of program (FSF, Debian, ...)
  85.  -L, --locale=STRING     select locale (default "C")
  86.  -i, --include=FILE      include material from `FILE'
  87.  -I, --opt-include=FILE  include material from `FILE' if it exists
  88.  -o, --output=FILE       send output to `FILE'
  89.  -p, --info-page=TEXT    name of Texinfo manual
  90.  -N, --no-info           suppress pointer to Texinfo manual
  91.      --help              print this help, then exit
  92.      --version           print version number, then exit
  93.  
  94. EXECUTABLE should accept `--help' and `--version' options although
  95. alternatives may be specified using:
  96.  
  97.  -h, --help-option=STRING     help option string
  98.  -v, --version-option=STRING  version option string
  99.  
  100. Report bugs to <bug-help2man@gnu.org>.
  101. EOT
  102.  
  103. my $section = 1;
  104. my $manual = '';
  105. my $source = '';
  106. my $locale = 'C';
  107. my $help_option = '--help';
  108. my $version_option = '--version';
  109. my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info);
  110.  
  111. my %opt_def = (
  112.     'n|name=s'         => \$opt_name,
  113.     's|section=s'     => \$section,
  114.     'm|manual=s'     => \$manual,
  115.     'S|source=s'     => \$source,
  116.     'L|locale=s'     => \$locale,
  117.     'i|include=s'     => sub { push @opt_include, [ pop, 1 ] },
  118.     'I|opt-include=s'     => sub { push @opt_include, [ pop, 0 ] },
  119.     'o|output=s'     => \$opt_output,
  120.     'p|info-page=s'     => \$opt_info,
  121.     'N|no-info'         => \$opt_no_info,
  122.     'h|help-option=s'     => \$help_option,
  123.     'v|version-option=s' => \$version_option,
  124. );
  125.  
  126. # Parse options.
  127. Getopt::Long::config('bundling');
  128. GetOptions (%opt_def,
  129.     help    => sub { print $help_info; exit },
  130.     version => sub { print $version_info; exit },
  131. ) or die $help_info;
  132.  
  133. die $help_info unless @ARGV == 1;
  134.  
  135. die "$this_program: no locale support (Locale::gettext required)\n"
  136.     unless $locale eq 'C' or $have_gettext;
  137.  
  138. # Set localisation of date and executable's ouput.
  139. delete @ENV{qw(LANGUAGE LC_MESSAGES LANG)};
  140. setlocale LC_ALL, $ENV{LC_ALL} = $locale;
  141.  
  142. my %include = ();
  143. my %append = ();
  144. my @include = (); # retain order given in include file
  145.  
  146. # Process include file (if given).  Format is:
  147. #
  148. #   [section name]
  149. #   verbatim text
  150. #
  151. # or
  152. #
  153. #   /pattern/
  154. #   verbatim text
  155. #
  156.  
  157. while (@opt_include)
  158. {
  159.     my ($inc, $required) = @{shift @opt_include};
  160.  
  161.     next unless -f $inc or $required;
  162.     kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $!
  163.     unless open INC, $inc;
  164.  
  165.     my $key;
  166.     my $hash = \%include;
  167.  
  168.     while (<INC>)
  169.     {
  170.     # [section]
  171.     if (/^\[([^]]+)\]/)
  172.     {
  173.         $key = uc $1;
  174.         $key =~ s/^\s+//;
  175.         $key =~ s/\s+$//;
  176.         $hash = \%include;
  177.         push @include, $key unless $include{$key};
  178.         next;
  179.     }
  180.  
  181.     # /pattern/
  182.     if (m!^/(.*)/([ims]*)!)
  183.     {
  184.         my $pat = $2 ? "(?$2)$1" : $1;
  185.  
  186.         # Check pattern.
  187.         eval { $key = qr($pat) };
  188.         if ($@)
  189.         {
  190.         $@ =~ s/ at .*? line \d.*//;
  191.         die "$inc:$.:$@";
  192.         }
  193.  
  194.         $hash = \%append;
  195.         next;
  196.     }
  197.  
  198.     # Check for options before the first section--anything else is
  199.     # silently ignored, allowing the first for comments and
  200.     # revision info.
  201.     unless ($key)
  202.     {
  203.         # handle options
  204.         if (/^-/)
  205.         {
  206.         local @ARGV = split;
  207.         GetOptions %opt_def;
  208.         }
  209.  
  210.         next;
  211.     }
  212.  
  213.     $hash->{$key} ||= '';
  214.     $hash->{$key} .= $_;
  215.     }
  216.  
  217.     close INC;
  218.  
  219.     kark N_("%s: no valid information found in `%s'"), $this_program, $inc
  220.         unless $key;
  221. }
  222.  
  223. # Compress trailing blank lines.
  224. for my $hash (\(%include, %append))
  225. {
  226.     for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
  227. }
  228.  
  229. # Grab help and version info from executable.
  230. my ($help_text, $version_text) = map {
  231.     join '', map { s/ +$//; expand $_ } `$ARGV[0] $_ 2>/dev/null`
  232.     or kark N_("%s: can't get `%s' info from %s"), $this_program,
  233.         $_, $ARGV[0]
  234. } $help_option, $version_option;
  235.  
  236. my $date = strftime "%B %Y", localtime;
  237. (my $program = $ARGV[0]) =~ s!.*/!!;
  238. my $package = $program;
  239. my $version;
  240.  
  241. if ($opt_output)
  242. {
  243.     unlink $opt_output or kark N_("%s: can't unlink %s (%s)"),
  244.         $this_program, $opt_output, $! if -e $opt_output;
  245.  
  246.     open STDOUT, ">$opt_output"
  247.     or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!;
  248. }
  249.  
  250. # The first line of the --version information is assumed to be in one
  251. # of the following formats:
  252. #
  253. #   <version>
  254. #   <program> <version>
  255. #   {GNU,Free} <program> <version>
  256. #   <program> ({GNU,Free} <package>) <version>
  257. #   <program> - {GNU,Free} <package> <version>
  258. #
  259. # and seperated from any copyright/author details by a blank line.
  260.  
  261. ($_, $version_text) = split /\n+/, $version_text, 2;
  262.  
  263. if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
  264.     /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
  265. {
  266.     $program = $1;
  267.     $package = $2;
  268.     $version = $3;
  269. }
  270. elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
  271. {
  272.     $program = $2;
  273.     $package = $1 ? "$1$2" : $2;
  274.     $version = $3;
  275. }
  276. else
  277. {
  278.     $version = $_;
  279. }
  280.  
  281. $program =~ s!.*/!!;
  282.  
  283. # No info for `info' itself.
  284. $opt_no_info = 1 if $program eq 'info';
  285.  
  286. # --name overrides --include contents.
  287. $include{_('NAME')} = "$program \\- $opt_name\n" if $opt_name;
  288.  
  289. # Default (useless) NAME paragraph.
  290. $include{_('NAME')} ||= sprintf _("%s \\- manual page for %s %s") . "\n",
  291.     $program, $program, $version;
  292.  
  293. # Man pages traditionally have the page title in caps.
  294. my $PROGRAM = uc $program;
  295.  
  296. # Set default page head/footers
  297. $source ||= "$program $version";
  298. unless ($manual)
  299. {
  300.     for ($section)
  301.     {
  302.     if (/^(1[Mm]|8)/) { $manual = _('System Administration Utilities') }
  303.     elsif (/^6/)      { $manual = _('Games') }
  304.     else          { $manual = _('User Commands') }
  305.     }
  306. }
  307.  
  308. # Extract usage clause(s) [if any] for SYNOPSIS.
  309. my $PAT_USAGE = _('Usage');
  310. my $PAT_USAGE_CONT = _('or');
  311. if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om)
  312. {
  313.     my @syn = $3 . $4;
  314.  
  315.     if ($_ = $5)
  316.     {
  317.     s/^\n//;
  318.     for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ }
  319.     }
  320.  
  321.     my $synopsis = '';
  322.     for (@syn)
  323.     {
  324.     $synopsis .= ".br\n" if $synopsis;
  325.     s!^\S*/!!;
  326.     s/^(\S+) *//;
  327.     $synopsis .= ".B $1\n";
  328.     s/\s+$//;
  329.     s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
  330.     s/^/\\fI/ unless s/^\\fR//;
  331.     $_ .= '\fR';
  332.     s/(\\fI)( *)/$2$1/g;
  333.     s/\\fI\\fR//g;
  334.     s/^\\fR//;
  335.     s/\\fI$//;
  336.     s/^\./\\&./;
  337.  
  338.     $synopsis .= "$_\n";
  339.     }
  340.  
  341.     $include{_('SYNOPSIS')} ||= $synopsis;
  342. }
  343.  
  344. # Process text, initial section is DESCRIPTION.
  345. my $sect = _('DESCRIPTION');
  346. $_ = "$help_text\n\n$version_text";
  347.  
  348. # Normalise paragraph breaks.
  349. s/^\n+//;
  350. s/\n*$/\n/;
  351. s/\n\n+/\n\n/g;
  352.  
  353. # Temporarily exchange leading dots, apostrophes and backslashes for
  354. # tokens.
  355. s/^\./\x80/mg;
  356. s/^'/\x81/mg;
  357. s/\\/\x82/g;
  358.  
  359. my $PAT_BUGS        = _('Report +bugs|Email +bug +reports +to');
  360. my $PAT_AUTHOR        = _('Written +by');
  361. my $PAT_OPTIONS        = _('Options');
  362. my $PAT_EXAMPLES    = _('Examples');
  363. my $PAT_FREE_SOFTWARE    = _('This +is +free +software');
  364.  
  365. # Start a new paragraph (if required) for these.
  366. s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR)/$1\n\n$2/og;
  367.  
  368. sub convert_option;
  369.  
  370. while (length)
  371. {
  372.     # Convert some standard paragraph names.
  373.     if (s/^($PAT_OPTIONS): *\n//o)
  374.     {
  375.     $sect = _('OPTIONS');
  376.     next;
  377.     }
  378.     elsif (s/^($PAT_EXAMPLES): *\n//o)
  379.     {
  380.     $sect = _('EXAMPLES');
  381.     next;
  382.     }
  383.  
  384.     # Copyright section
  385.     if (/^Copyright +[(\xa9]/)
  386.     {
  387.     $sect = _('COPYRIGHT');
  388.     $include{$sect} ||= '';
  389.     $include{$sect} .= ".PP\n" if $include{$sect};
  390.  
  391.     my $copy;
  392.     ($copy, $_) = split /\n\n/, $_, 2;
  393.  
  394.     for ($copy)
  395.     {
  396.         # Add back newline
  397.         s/\n*$/\n/;
  398.  
  399.         # Convert iso9959-1 copyright symbol or (c) to nroff
  400.         # character.
  401.         s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
  402.  
  403.         # Insert line breaks before additional copyright messages
  404.         # and the disclaimer.
  405.         s/(.)\n(Copyright |$PAT_FREE_SOFTWARE)/$1\n.br\n$2/og;
  406.  
  407.         # Join hyphenated lines.
  408.         s/([A-Za-z])-\n */$1/g;
  409.     }
  410.  
  411.     $include{$sect} .= $copy;
  412.     $_ ||= '';
  413.     next;
  414.     }
  415.  
  416.     # Catch bug report text.
  417.     if (/^($PAT_BUGS) /o)
  418.     {
  419.     $sect = _('REPORTING BUGS');
  420.     }
  421.  
  422.     # Author section.
  423.     elsif (/^($PAT_AUTHOR)/o)
  424.     {
  425.     $sect = _('AUTHOR');
  426.     }
  427.  
  428.     # Examples, indicated by an indented leading $, % or > are
  429.     # rendered in a constant width font.
  430.     if (/^( +)([\$\%>] )\S/)
  431.     {
  432.     my $indent = $1;
  433.     my $prefix = $2;
  434.     my $break = '.IP';
  435.     $include{$sect} ||= '';
  436.     while (s/^$indent\Q$prefix\E(\S.*)\n*//)
  437.     {
  438.         $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
  439.         $break = '.br';
  440.     }
  441.  
  442.     next;
  443.     }
  444.  
  445.     my $matched = '';
  446.     $include{$sect} ||= '';
  447.  
  448.     # Sub-sections have a trailing colon and the second line indented.
  449.     if (s/^(\S.*:) *\n / /)
  450.     {
  451.     $matched .= $& if %append;
  452.     $include{$sect} .= qq(.SS "$1"\n);
  453.     }
  454.  
  455.     my $indent = 0;
  456.     my $content = '';
  457.  
  458.     # Option with description.
  459.     if (s/^( {1,10}([+-]\S.*?))(?:(  +(?!-))|\n( {20,}))(\S.*)\n//)
  460.     {
  461.     $matched .= $& if %append;
  462.     $indent = length ($4 || "$1$3");
  463.     $content = ".TP\n\x83$2\n\x83$5\n";
  464.     unless ($4)
  465.     {
  466.         # Indent may be different on second line.
  467.         $indent = length $& if /^ {20,}/;
  468.     }
  469.     }
  470.  
  471.     # Option without description.
  472.     elsif (s/^ {1,10}([+-]\S.*)\n//)
  473.     {
  474.     $matched .= $& if %append;
  475.     $content = ".HP\n\x83$1\n";
  476.     $indent = 80; # not continued
  477.     }
  478.  
  479.     # Indented paragraph with tag.
  480.     elsif (s/^( +(\S.*?)  +)(\S.*)\n//)
  481.     {
  482.     $matched .= $& if %append;
  483.     $indent = length $1;
  484.     $content = ".TP\n\x83$2\n\x83$3\n";
  485.     }
  486.  
  487.     # Indented paragraph.
  488.     elsif (s/^( +)(\S.*)\n//)
  489.     {
  490.     $matched .= $& if %append;
  491.     $indent = length $1;
  492.     $content = ".IP\n\x83$2\n";
  493.     }
  494.  
  495.     # Left justified paragraph.
  496.     else
  497.     {
  498.     s/(.*)\n//;
  499.     $matched .= $& if %append;
  500.     $content = ".PP\n" if $include{$sect};
  501.     $content .= "$1\n";
  502.     }
  503.  
  504.     # Append continuations.
  505.     while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//)
  506.     {
  507.     $matched .= $& if %append;
  508.     $content .= "\x83$1\n"
  509.     }
  510.  
  511.     # Move to next paragraph.
  512.     s/^\n+//;
  513.  
  514.     for ($content)
  515.     {
  516.     # Leading dot and apostrophe protection.
  517.     s/\x83\./\x80/g;
  518.     s/\x83'/\x81/g;
  519.     s/\x83//g;
  520.  
  521.     # Convert options.
  522.     s/(^| )(-[][\w=-]+)/$1 . convert_option $2/mge;
  523.     }
  524.  
  525.     # Check if matched paragraph contains /pat/.
  526.     if (%append)
  527.     {
  528.     for my $pat (keys %append)
  529.     {
  530.         if ($matched =~ $pat)
  531.         {
  532.         $content .= ".PP\n" unless $append{$pat} =~ /^\./;
  533.         $content .= $append{$pat};
  534.         }
  535.     }
  536.     }
  537.  
  538.     $include{$sect} .= $content;
  539. }
  540.  
  541. # Refer to the real documentation.
  542. unless ($opt_no_info)
  543. {
  544.     my $info_page = $opt_info || $program;
  545.  
  546.     $sect = _('SEE ALSO');
  547.     $include{$sect} ||= '';
  548.     $include{$sect} .= ".PP\n" if $include{$sect};
  549.     $include{$sect} .= sprintf _(<<'EOT'), $program, $info_page, $info_page;
  550. The full documentation for
  551. .B %s
  552. is maintained as a Texinfo manual.  If the
  553. .B info
  554. and
  555. .B %s
  556. programs are properly installed at your site, the command
  557. .IP
  558. .B info %s
  559. .PP
  560. should give you access to the complete manual.
  561. EOT
  562. }
  563.  
  564. # Output header.
  565. print <<EOT;
  566. .\\" DO NOT MODIFY THIS FILE!  It was generated by $this_program $this_version.
  567. .TH $PROGRAM "$section" "$date" "$source" "$manual"
  568. EOT
  569.  
  570. # Section ordering.
  571. my @pre = (_('NAME'), _('SYNOPSIS'), _('DESCRIPTION'), _('OPTIONS'),
  572.     _('EXAMPLES'));
  573.  
  574. my @post = (_('AUTHOR'), _('REPORTING BUGS'), _('COPYRIGHT'), _('SEE ALSO'));
  575. my $filter = join '|', @pre, @post;
  576.  
  577. # Output content.
  578. for my $sect (@pre, (grep ! /^($filter)$/o, @include), @post)
  579. {
  580.     if ($include{$sect})
  581.     {
  582.     my $lsect = gettext $sect;
  583.     my $quote = $lsect =~ /\W/ ? '"' : '';
  584.     print ".SH $quote$lsect$quote\n";
  585.  
  586.     for ($include{$sect})
  587.     {
  588.         # Replace leading dot, apostrophe and backslash tokens.
  589.         s/\x80/\\&./g;
  590.         s/\x81/\\&'/g;
  591.         s/\x82/\\e/g;
  592.  
  593.         # Convert some latin1 chars to troff equivalents
  594.         s/\xa0/\\ /g; # non-breaking space
  595.  
  596.         print;
  597.     }
  598.     }
  599. }
  600.  
  601. close STDOUT or kark N_("%s: error writing to %s (%s)"), $this_program,
  602.     $opt_output || 'stdout', $!;
  603.  
  604. exit;
  605.  
  606. # Convert option dashes to \- to stop nroff from hyphenating 'em, and
  607. # embolden.  Option arguments get italicised.
  608. sub convert_option
  609. {
  610.     local $_ = '\fB' . shift;
  611.  
  612.     s/-/\\-/g;
  613.     unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
  614.     {
  615.     s/=(.)/\\fR=\\fI$1/;
  616.     s/ (.)/ \\fI$1/;
  617.     $_ .= '\fR';
  618.     }
  619.  
  620.     $_;
  621. }
  622.